home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- ;=============================================================================
- ; STAYDOWN holds the CTRL, ALT, and SHIFT keys temporarily toggled on,
- ; allowing keystroke combinations to be entered with sequential rather
- ; than simultaneous keypresses. Syntax is:
- ;
- ; STAYDOWN [/D | /U]
- ;
- ; where /D disables the program until it is run again from the
- ; command line, and /U uninstalls it.
- ;=============================================================================
-
- KBDATA EQU 60H ;Keyboard data port
- KBCTRL EQU 61H ;Keyboard control port
- ALT EQU 38H ;Scan code for ALT key
- CTRL EQU 1DH ;Scan code for CTRL key
- LSHIFT EQU 2AH ;Scan code for left SHIFT key
- RSHIFT EQU 36H ;Scan code for right SHIFT key
- CR EQU 0DH
- LF EQU 0AH
-
- ;=============================================================================
- ;BIOS Data Area
- ;=============================================================================
- BIOS_DATA SEGMENT AT 40H
- ORG 17H
- SHIFT_STATE_1 DB ? ;Primary shift state byte
- SHIFT_STATE_2 DB ? ;Left CTRL/ALT (bits 0, 1)
- ORG 96H
- SHIFT_STATE_3 DB ? ;Right CTRL/ALT (bits 2, 3)
- BIOS_DATA ENDS
-
- ;=============================================================================
- ;Code Segment (code and data)
- ;=============================================================================
- CODE SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE
- ORG 100H
- BEGIN: JMP INITIALIZE
-
- PROGRAM DB "STAYDOWN 1.0 (c) 1988 Ziff Communications Co.",CR,LF
- AUTHOR DB "PC Magazine ",254," Jeff Prosise",CR,LF,"$",1AH
-
- CHECKFLAG DB ? ;Enable/disable flag
- RESTORE_FLAG DB 0 ;Break code ignored flag
- LAST_SCAN_CODE DB 0 ;Last scan code
- EO_FLAG DB 0 ;80h = last code was E0h
- KB_VECTOR DB 15H ;Vector altered to trap keys
-
- BIOS_ISR LABEL DWORD
- OLD_VECTOR DW 2 DUP (?) ;Old interrupt 9/15h vector
-
- ;-----------------------------------------------------------------------------
- ;INT9H handles interrupt 9 on machines that lack interrupt 15h keyboard
- ;processing facilities.
- ;-----------------------------------------------------------------------------
- INT9H PROC FAR
- ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
-
- CMP CS:CHECKFLAG,0 ;Exit to BIOS if program
- JE PASS_TO_BIOS ; isn't currently enabled
-
- STI ;Interrupts on
- PUSH AX
- IN AL,KBDATA ;Read scan code from keyboard
- CALL MAIN ;Perform internal processing
- JNC RESET_KEYBOARD ;Ignore scan code if CF = 0
- POP AX
- PASS_TO_BIOS: JMP CS:BIOS_ISR ;Jump to BIOS int handler
-
- RESET_KEYBOARD: IN AL,KBCTRL ;Reset the keyboard
- MOV AH,AL
- OR AL,80H
- OUT KBCTRL,AL
- MOV AL,AH
- OUT KBCTRL,AL
- CLI
- MOV AL,20H ;Signal EOI to interrupt
- OUT 20H,AL ; controller
- STI
- POP AX
- IRET ;Exit without processing
-
- INT9H ENDP
-
- ;-----------------------------------------------------------------------------
- ;INT15H handles interrupt 15h on machines with an extended BIOS.
- ;-----------------------------------------------------------------------------
- INT15H PROC FAR
- ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
-
- CMP AH,4FH ;Exit to BIOS handler if
- JNE EXIT_TO_BIOS ; function code <> 4Fh
-
- STI ;Interrupt on
- CMP CS:CHECKFLAG,0 ;Process scan code as normal
- JE PROCESS_SCAN_CODE ; if program is disabled
-
- CMP AL,0E0H ;Set flag and terminate if
- JNE NOT_EO ; scan code = E0h
- MOV CS:EO_FLAG,80H
- JMP SHORT PROCESS_SCAN_CODE
-
- NOT_EO: CMP CS:EO_FLAG,0 ;Branch if E0 flag not set
- JE CHECK_CODE
- CMP AL,2AH ;If this scan code is part of
- JE RESET_EO_FLAG ; a 4-code sequence, then
- CMP AL,0AAH ; reset E0 flag and process
- JE RESET_EO_FLAG ; the scan code
- CMP AL,36H
- JE RESET_EO_FLAG
- CMP AL,0B6H
- JNE CHECK_CODE
-
- RESET_EO_FLAG: MOV CS:EO_FLAG,0 ;Reset flag
- JMP SHORT PROCESS_SCAN_CODE ;Process the scan code
-
- CHECK_CODE: PUSH AX
- CALL MAIN ;Perform internal processing
- MOV CS:EO_FLAG,0
- POP AX
- RET 2 ;Return with flags intact
-
- PROCESS_SCAN_CODE:
- STC ;Set CF for BIOS processing
- RET 2 ;Return with flags intact
- EXIT_TO_BIOS: JMP CS:BIOS_ISR ;Pass to BIOS for processing
-
- INT15H ENDP
-
- ;-----------------------------------------------------------------------------
- ;MAIN is called by the two interrupt handling routines to process a keystroke.
- ;Entry: AL - scan code
- ;-----------------------------------------------------------------------------
- MAIN PROC NEAR
- ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
-
- TEST AL,80H ;Branch on break code
- JNZ BREAK_CODE
- ;
- ;Process a make code by simply saving the scan code.
- ;
- OR AL,CS:EO_FLAG ;Save E0h indicator
- MOV CS:LAST_SCAN_CODE,AL ;Save make code
- STC ;Exit with CF = 1
- RET
- ;
- ;A break code was received.
- ;
- BREAK_CODE: CMP CS:RESTORE_FLAG,0 ;Branch if shift bits are
- JNE RESTORE_SHIFT_BYTES ; out of sync
- AND AL,7FH ;Strip break bit
- OR AL,CS:EO_FLAG ;Add E0h indicator
- CMP AL,CS:LAST_SCAN_CODE ;Branch if the key released
- JE CHECK_FOR_SHIFT ; was the last one pressed
- PROCESS_BREAK: MOV LAST_SCAN_CODE,0 ;Process break code as normal
- STC
- RET
- ;
- ;Ignore the break if the key just released was a shift key.
- ;
- CHECK_FOR_SHIFT:
- CMP AL,ALT ;Check codes for ALT, CTRL,
- JE IGNORE_BREAK ; and SHIFT keys
- CMP AL,ALT+80H
- JE IGNORE_BREAK
- CMP AL,CTRL
- JE IGNORE_BREAK
- CMP AL,CTRL+80H
- JE IGNORE_BREAK
- CMP AL,LSHIFT
- JE IGNORE_BREAK
- CMP AL,RSHIFT
- JNE PROCESS_BREAK
- IGNORE_BREAK: MOV CS:RESTORE_FLAG,AL ;Ignore the break code
- MOV CS:LAST_SCAN_CODE,0
- CLC ;Return with CF = 0
- RET
- ;
- ;Reset the BIOS shift bit(s) corresponding to the last key release ignored.
- ;
- RESTORE_SHIFT_BYTES:
- MOV AL,CS:RESTORE_FLAG ;Recover ignored scan code
- MOV CS:RESTORE_FLAG,0 ;Reset flag
- PUSH ES ;Point ES to BIOS data area
- PUSH AX
- MOV AX,40H
- MOV ES,AX
- POP AX
-
- CMP AL,RSHIFT ;Reset a single bit if
- JNE NOT_RSHIFT ; right SHIFT key was
- AND ES:[SHIFT_STATE_1],0FEH ; released
- JMP SHORT END_RESTORE
-
- NOT_RSHIFT: CMP AL,LSHIFT ;Likewise for left SHIFT
- JNE NOT_LSHIFT
- AND ES:[SHIFT_STATE_1],0FDH
- JMP SHORT END_RESTORE
-
- NOT_LSHIFT: CMP AL,CTRL+80H ;Reset right CTRL key bit
- JNE NOT_RCTRL
- AND ES:[SHIFT_STATE_3],0FBH
- JMP SHORT FIX_PRIMARY_SHIFT
-
- NOT_RCTRL: CMP AL,CTRL ;Reset two left CTRL bits
- JNE NOT_LCTRL
- AND ES:[SHIFT_STATE_1],0FBH
- AND ES:[SHIFT_STATE_2],0FEH
- TEST ES:[SHIFT_STATE_3],10H ;Branch for further processing
- JZ END_RESTORE ; if this is a 101-key
- JMP SHORT FIX_PRIMARY_SHIFT ; keyboard
-
- NOT_LCTRL: CMP AL,ALT+80H ;Reset right ALT bit
- JNE NOT_RALT
- AND ES:[SHIFT_STATE_3],0F7H
- JMP SHORT FIX_PRIMARY_SHIFT
-
- NOT_RALT: AND ES:[SHIFT_STATE_1],0F7H ;Reset two left ALT bits
- AND ES:[SHIFT_STATE_2],0FDH
- TEST ES:[SHIFT_STATE_3],10H ;Test for 101-key keyboard
- JZ END_RESTORE ;Branch if it's not
-
- FIX_PRIMARY_SHIFT:
- MOV AH,ES:[SHIFT_STATE_2] ;Set CTRL/ALT bits in primary
- SHL AH,1 ; shift state byte if either
- SHL AH,1 ; left or right CTRL/ALT is
- OR AH,ES:[SHIFT_STATE_3] ; pressed
- AND AH,0CH
- AND ES:[SHIFT_STATE_1],0F3H
- OR ES:[SHIFT_STATE_1],AH
- END_RESTORE: POP ES
- JMP PROCESS_BREAK ;Process the break code
- MAIN ENDP
-
- ;-----------------------------------------------------------------------------
- ;INITIALIZE installs the program into memory.
- ;-----------------------------------------------------------------------------
- HEADMSG DB CR,LF,"STAYDOWN: $"
- ERRMSG1 DB "Usage: STAYDOWN [/D][/U]",CR,LF,"$"
- ERRMSG2 DB "Not Installed",CR,LF,"$"
- ERRMSG3 DB "Cannot Uninstall",CR,LF,"$"
- ERRMSG4 DB "Uninstall Error",CR,LF,"$"
- CONFIRM_MSG1 DB "Disabled",CR,LF,"$"
- CONFIRM_MSG2 DB "Uninstalled",CR,LF,"$"
- CONFIRM_MSG3 DB "Activated",CR,LF,"$"
-
- INSTALL_FLAG DB 0
-
- INITIALIZE PROC NEAR
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
- ;
- ;See if STAYDOWN is already installed.
- ;
- CLD ;Clear DF
- NOT WORD PTR [BEGIN] ;Initialize fingerprint
- XOR BX,BX ;Initialize segment values
- MOV AX,CS
- ASSUME ES:NOTHING
-
- INIT1: INC BX ;Advance to next segment
- MOV ES,BX
- CMP AX,BX ;End search if we loop back
- JE PARSE ; to the current segment
- MOV SI,OFFSET BEGIN ;Check for ASCII fingerprint
- MOV DI,SI
- MOV CX,16
- REPE CMPSB
- JNE INIT1 ;Loop if not found
- MOV INSTALL_FLAG,1 ;Program is already installed
- ;
- ;Parse the command line for a /D or /U parameter.
- ;
- PARSE: MOV SI,81H ;Point DS:SI to command line
- PARSE1: CMP BYTE PTR [SI],32 ;Advance to first non-space
- JNE PARSE2
- INC SI
- JMP SHORT PARSE1
-
- PARSE2: CMP BYTE PTR [SI],CR ;End-of-line?
- JE INSTALL ;Yes, then install/enable
- AND BYTE PTR [SI+1],0DFH ;Capitalize entry
- CMP WORD PTR [SI],442FH ;Qualifier /D?
- JE DISABLE ;Yes, then disable program
- CMP WORD PTR [SI],552FH ;Qualifier /U?
- JE UNINSTALL ;Yes, then uninstall program
-
- MOV AL,1 ;Error code
- MOV DX,OFFSET ERRMSG1 ;Error message address
- ERROR_EXIT:
- PUSH AX ;Save registers
- PUSH DX
-
- MOV DX,OFFSET HEADMSG ;Display prologue
- MOV AH,9
- INT 21H
-
- POP DX ;Display error
- MOV AH,9
- INT 21H
-
- POP AX ;Error code
- MOV AH,4CH ;Terminate with ERRORLEVEL set
- INT 21H
- ;
- ;Disable STAYDOWN if a copy is present in memory.
- ;
- DISABLE:
- CMP INSTALL_FLAG,1 ;Error if not installed
- JE DISABLE2
-
- MOV AL,2
- MOV DX,OFFSET ERRMSG2 ;Initialize error pointer
- JMP ERROR_EXIT
- DISABLE2:
- MOV ES:[CHECKFLAG],0 ;Clear CHECKFLAG byte
- MOV DX,OFFSET CONFIRM_MSG1 ;Print confirmation message
- CONFIRM_AND_EXIT:
- PUSH DX
-
- MOV DX,OFFSET HEADMSG
- MOV AH,9
- INT 21H
-
- POP DX
- MOV AH,9
- INT 21H
-
- MOV AX,4C00H ;Exit with ERRORLEVEL = 0
- INT 21H
- ;
- ;Uninstall STAYDOWN if a copy is present in memory.
- ;
- UNINSTALL:
-
- CMP INSTALL_FLAG,1 ;Error if not installed
- JE UNINSTALL2
-
- MOV AL,3
- MOV DX,OFFSET ERRMSG2 ;Initialize error pointer
- JMP ERROR_EXIT
- UNINSTALL2:
- CALL REMOVE ;Uninstall the program
- JNC UNINSTALL3
-
- MOV AL,4
- JMP ERROR_EXIT
- UNINSTALL3:
- MOV DX,OFFSET CONFIRM_MSG2 ;Print confirmation message
- JMP SHORT CONFIRM_AND_EXIT ;And exit
- ;
- ;Install the program if it isn't already installed, or enable it if it is.
- ;
- INSTALL: MOV ES:[CHECKFLAG],1 ;Set enable byte
- CMP INSTALL_FLAG,1 ;Branch if not installed
- JNE INSTALL1
- MOV DX,OFFSET CONFIRM_MSG3 ;Print confirmation message
- JMP SHORT CONFIRM_AND_EXIT ;And exit
-
- INSTALL1: MOV AH,0C0H ;Check for BIOS support of
- INT 15H ; extended functions
- MOV DX,OFFSET INT15H
- JNC INSTALL2 ;Branch if support is there
- MOV KB_VECTOR,9 ;Use int 9 rather than 15h
- MOV DX,OFFSET INT9H ;Point DX to int 9 routine
-
- INSTALL2: MOV AH,35H ;Save current vector
- MOV AL,KB_VECTOR
- INT 21H
- MOV OLD_VECTOR,BX
- MOV OLD_VECTOR[2],ES
- MOV AH,25H ;Then point it to internal
- MOV AL,KB_VECTOR ; interrupt handler
- INT 21H
-
- MOV AX,DS:[2CH] ;Get environment segment
- MOV ES,AX ; address from PSP
- MOV AH,49H ;Then deallocate environment
- INT 21H ; space reserved by DOS
-
- MOV AH,9 ;Print installation message
- MOV DX,OFFSET PROGRAM
- INT 21H
-
- MOV AX,3100H ;Terminate but remain resident
- MOV DX,(OFFSET INITIALIZE-OFFSET CODE+15) SHR 4
- INT 21H
-
- INITIALIZE ENDP
-
- ;-----------------------------------------------------------------------------
- ;REMOVE deallocates the memory block addressed by ES and restores the
- ;Interrupt vector displaced on installation.
- ;-----------------------------------------------------------------------------
- REMOVE PROC NEAR
-
- PUSH ES ;Get current interrupt 9/15h
- MOV AH,35H ; vector and see if STAYDOWN
- MOV AL,ES:[KB_VECTOR] ; still owns it
- INT 21H
-
- MOV BX,ES
- POP ES
- MOV AX,ES
- CMP BX,AX ;Program cannot be uninstalled
- JE RESTORE_VECTOR ; if interrupt 9/15h vector
- MOV DX,OFFSET ERRMSG3 ; has been grabbed away
- STC ;Return with CF = 1 for error
- RET
- RESTORE_VECTOR:
- PUSH DS ;Restore displaced interrupt
- ASSUME DS:NOTHING ; vector
-
- LDS DX,ES:[BIOS_ISR]
- MOV AH,25H
- MOV AL,ES:[KB_VECTOR]
- INT 21H
- POP DS
- ASSUME DS:CODE
-
- NOT WORD PTR ES:[BEGIN] ;Remove fingerprint
-
- MOV AH,49H ;Free memory given to
- INT 21H ; original program block
- MOV DX,OFFSET ERRMSG4 ;Initialize error pointer
- RET ;Exit with CF intact
-
- REMOVE ENDP
-
- CODE ENDS
- END BEGIN
-